/*
 * NIST Healthcare Test Framework
 * SoapUtils.java Jul 30, 2010
 *
 * This code was produced by the National Institute of Standards and
 * Technology (NIST). See the "nist.disclaimer" file given in the distribution
 * for information on the use and redistribution of this software.
 */
package gov.nist.healthcare.testframework.communication;

import gov.nist.healthcare.core.MalformedMessageException;
import gov.nist.healthcare.core.message.HL7Message;
import gov.nist.healthcare.core.message.v3.HL7V3Message;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.SOAPException;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.impl.DefaultHttpClientConnection;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.params.BasicHttpParams;
import org.apache.log4j.Logger;
import org.apache.xmlbeans.XmlException;
import org.xml.sax.SAXException;

/**
 * This class contains methods to deal with the SOAP protocol.
 * 
 * @author Sydney Henrard (NIST)
 */
public class SoapUtils {

    private static final Logger logger = Logger.getLogger(SoapUtils.class.getName());

    /**
     * Wrap a message to be sent as a HTTP Response
     * 
     * @param message
     * @return the wrapped message
     */
    public static String wrapMessageInHttpResponse(HL7Message message) {
        // String wrappedMessage = null;
        // try {
        // HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,
        // HttpStatus.SC_OK, "OK");
        // // SOAP Wrapper
        // MessageFactory soapMessageFactory =
        // MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        // SOAPMessage soapMessage = soapMessageFactory.createMessage();
        // SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
        // XmlObject xmlEnvelope = XmlObject.Factory.parse(soapEnvelope);
        // XmlCursor soapCursor = xmlEnvelope.newCursor();
        // soapCursor.toNextToken();
        // soapCursor.toChild("http://www.w3.org/2003/05/soap-envelope",
        // "Body");
        // soapCursor.toNextToken();
        // XmlCursor messageCursor = ((HL7V3Message)
        // message).getDocument().newCursor();
        // messageCursor.toFirstChild();
        // messageCursor.copyXml(soapCursor);
        // soapCursor.toStartDoc();
        // StringEntity content = new StringEntity(soapCursor.xmlText());
        // wrappedMessage = String.format(
        // "%s\nContent-Type: %s\nContent-Length: %d\n\n%s\n",
        // response.getStatusLine(), content.getContentType(),
        // content.getContentLength(), soapCursor.xmlText());
        // soapCursor.dispose();
        // } catch (SOAPException soap) {
        // logger.debug("Exception when creating the SOAP message", soap);
        // } catch (XmlException xml) {
        // logger.debug("Exception when manipulating the SOAP message", xml);
        // } catch (UnsupportedEncodingException uee) {
        // logger.debug("Exception when creating the entity", uee);
        // }
        // return wrappedMessage;

        // Michael's proposed changes
        String toreturn = "";
        try {
            HSV3Response toencode = new HSV3Response((HL7V3Message) message);
            toreturn = toencode.getStringRepresentation();
        } catch (SOAPException soapex) {
            logger.debug("Error parsing HL7V3Message into a SOAP object: \n"
                    + soapex.getMessage());
        } catch (SAXException saxex) {
            logger.debug("Error parsing the XML in the HL7V3Message: \n"
                    + saxex.getMessage());
        } catch (IOException ioe) {
            logger.debug("IOException " + ioe);
        } catch (Exception e) {
            logger.debug("Failed during encode: " + e.getMessage());
        }

        return toreturn;
    }

    /**
     * Wrap a message to be sent as a HTTP Request
     * 
     * @param message
     * @param endpoint
     * @return the wrapped message
     */
    public static String wrapMessageInHttpRequest(HL7Message message,
            String endpoint) {
        // String wrappedSendingMessage = null;
        // try {
        // HttpRequest request = new BasicHttpEntityEnclosingRequest("POST",
        // endpoint, HttpVersion.HTTP_1_1);
        // // SOAP Wrapper
        // MessageFactory soapMessageFactory =
        // MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        // SOAPMessage soapMessage = soapMessageFactory.createMessage();
        // SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
        // XmlObject xmlEnvelope = XmlObject.Factory.parse(soapEnvelope);
        // XmlCursor soapCursor = xmlEnvelope.newCursor();
        // soapCursor.toNextToken();
        // soapCursor.toChild("http://www.w3.org/2003/05/soap-envelope",
        // "Body");
        // soapCursor.toNextToken();
        // XmlCursor messageCursor = ((HL7V3Message)
        // message).getDocument().newCursor();
        // messageCursor.toFirstChild();
        // messageCursor.copyXml(soapCursor);
        // soapCursor.toStartDoc();
        // StringEntity content = new StringEntity(soapCursor.xmlText());
        // wrappedSendingMessage = String.format(
        // "%s\nContent-Type: %s\nContent-Length: %d\n\n%s\n",
        // request.getRequestLine(), content.getContentType(),
        // content.getContentLength(), soapCursor.xmlText());
        // soapCursor.dispose();
        // } catch (SOAPException soap) {
        // logger.debug("Exception when creating the SOAP message", soap);
        // } catch (XmlException xml) {
        // logger.debug("Exception when manipulating the SOAP message", xml);
        // } catch (UnsupportedEncodingException uee) {
        // logger.debug("Exception when creating the entity", uee);
        // }
        // return wrappedSendingMessage;

        // Michael's proposed changes
        String encoded_message = "";
        try {
            HSV3Request toencode = new HSV3Request((HL7V3Message) message,
                    endpoint);
            encoded_message = toencode.getStringRepresentation();
        } catch (SOAPException soap) {
            logger.debug("Exception when creating the SOAP message", soap);
        } catch (UnsupportedEncodingException uee) {
            logger.debug("Exception when creating the entity", uee);
        } catch (IOException ioe) {
            logger.debug("IOException", ioe);
        } catch (SAXException saxe) {
            logger.debug("SAXException", saxe);
        } catch (ParserConfigurationException e) {
            logger.debug("A problem occured while parsing the message: "
                    + e.getMessage());
        }
        return encoded_message;
    }

    /**
     * Unwrap the message from a HTTP Response
     * 
     * @param socket
     * @return the message
     * @throws IOException
     */
    public static String unWrapMessageFromHttpResponse(Socket socket)
            throws IOException {
        // HL7Message message = null;
        // try {
        // BasicHttpParams params = new BasicHttpParams();
        // DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
        // conn.bind(socket, params);
        // HttpResponse response = conn.receiveResponseHeader();
        // conn.receiveResponseEntity(response);
        // HttpEntity entity = response.getEntity();
        // if (entity != null) {
        // MessageFactory soapMessageFactory =
        // MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        // SOAPMessage soapMessage = soapMessageFactory.createMessage(
        // new MimeHeaders(), entity.getContent());
        // SOAPBody soapBody = soapMessage.getSOAPBody();
        // XmlObject xml = XmlObject.Factory.parse(soapBody);
        // XmlCursor cursor = xml.newCursor();
        // cursor.toFirstChild();
        // message = new HL7V3Message(cursor.getObject().xmlText());
        // cursor.dispose();
        // entity.consumeContent();
        // }
        // } catch (HttpException http) {
        // logger.debug("Exception when reading the HTTP connection", http);
        // } catch (SOAPException soap) {
        // logger.debug("Exception when parsing the SOAP message", soap);
        // } catch (XmlException xml) {
        // logger.debug("Exception when creating the HL7V3 message", xml);
        // } catch (MalformedMessageException mme) {
        // logger.debug("Exception when creating the HL7V3 message", mme);
        // }
        // return message.getMessageAsString();

        // Michael's proposed changes
        HL7Message message = null;
        try {
            BasicHttpParams params = new BasicHttpParams();
            DefaultHttpClientConnection conn = new DefaultHttpClientConnection();
            conn.bind(socket, params);
            HttpResponse response = conn.receiveResponseHeader();
            conn.receiveResponseEntity(response);
            HSV3Response current_response = new HSV3Response(
                    (BasicHttpResponse) response);

            try {
                if (current_response.isWSAValid()) {
                    logger.debug("WSA Header Correct");
                }
            } catch (WSAException wse) {
                logger.debug(wse.getMessage());
            }
            message = current_response.getV3payload();

        } catch (HttpException http) {
            logger.debug("Exception when reading the HTTP connection", http);
        } catch (SOAPException soap) {
            logger.debug("Exception when parsing the SOAP message", soap);
        } catch (XmlException xml) {
            logger.debug("Exception when creating the HL7V3 message", xml);
        } catch (MalformedMessageException mme) {
            logger.debug("Exception when creating the HL7V3 message", mme);
        }
        return message.getMessageAsString();
    }

    /**
     * Unwrap the message from a HTTP Request
     * 
     * @param socket
     * @return the message
     * @throws IOException
     */
    public static String unWrapMessageFromHttpRequest(Socket socket)
            throws IOException {
        // HL7Message message = null;
        // try {
        // BasicHttpParams params = new BasicHttpParams();
        // DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
        // conn.bind(socket, params);
        // HttpRequest request = conn.receiveRequestHeader();
        // if (request instanceof HttpEntityEnclosingRequest) {
        // conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);
        // HttpEntity entity = ((HttpEntityEnclosingRequest)
        // request).getEntity();
        // if (entity != null) {
        // MessageFactory soapMessageFactory =
        // MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        // SOAPMessage soapMessage = soapMessageFactory.createMessage(
        // new MimeHeaders(), entity.getContent());
        // SOAPBody soapBody = soapMessage.getSOAPBody();
        // XmlObject xml = XmlObject.Factory.parse(soapBody);
        // XmlCursor cursor = xml.newCursor();
        // cursor.toFirstChild();
        // message = new HL7V3Message(cursor.getObject().xmlText());
        // cursor.dispose();
        // entity.consumeContent();
        // }
        // }
        // } catch (HttpException http) {
        // logger.debug("Exception when reading the HTTP connection", http);
        // } catch (SOAPException soap) {
        // logger.debug("Exception when parsing the SOAP message", soap);
        // } catch (XmlException xml) {
        // logger.debug("Exception when creating the HL7V3 message", xml);
        // } catch (MalformedMessageException mme) {
        // logger.debug("Exception when creating the HL7V3 message", mme);
        // }
        // return message.getMessageAsString();

        // Micheal's proposed changes
        HL7Message extracted_message = null;
        String extracted_string = "";
        try {
            HSV3Request incoming_request;
            BasicHttpParams params = new BasicHttpParams();
            DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
            conn.bind(socket, params);
            HttpRequest request;

            request = conn.receiveRequestHeader();

            conn.receiveRequestEntity((HttpEntityEnclosingRequest) request);

            incoming_request = new HSV3Request(
                    (HttpEntityEnclosingRequest) request);

            // Check for WSA
            try {
                incoming_request.isWSAValid();
            } catch (Exception e) {
                logger.debug("");
            }
            extracted_message = incoming_request.getV3payload();
            extracted_string = extracted_message.getMessageAsString();
        } catch (HttpException http) {
            logger.debug("Exception when reading the HTTP connection", http);
        } catch (SOAPException soap) {
            logger.debug("Exception when parsing the SOAP message", soap);
        } catch (XmlException xml) {
            logger.debug("Exception when creating the HL7V3 message", xml);
        } catch (MalformedMessageException mme) {
            logger.debug("Exception when creating the HL7V3 message", mme);
        }

        return extracted_string;
    }
}
